﻿using DirectoryServicesProtocolsExtensions.MetaData;

namespace IntegrationTests.SchemaConversionTests
{
    using System;
    using System.Diagnostics;
    using System.Security.Principal;
    using DirectoryServicesProtocolsExtensions.LdapConnection;
    using DirectoryServicesProtocolsExtensions.LdapConnection.MetaData;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class LdapSchemaToDotNetTypeConversionTests : LdapTest, ILdapSchemaConversionRequiredTests
    {
        [TestMethod]
        public void ObjectGUIDTest()
        {
            var timer = new Stopwatch();
            timer.Start();
            var objectGUIDMetaMapping = LdapConnection.GetAttributeMetaData("objectGUID", LdapMetaMapFactory);
            Assert.IsTrue(objectGUIDMetaMapping.RawDotNetTypeEquivalent == typeof(byte[]));
            Assert.IsTrue(objectGUIDMetaMapping.SemanticDotNetTypeEquivalent == typeof(Guid));
            Assert.IsTrue(objectGUIDMetaMapping.SemanticValueConversionFunction == LdapValueDecoder.DecodeObjectGUIDValue);
            Assert.IsFalse(objectGUIDMetaMapping.IsMultiValued);
            Assert.IsFalse(objectGUIDMetaMapping.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("ObjectGUID MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }

        [TestMethod]
        public void ObjectSIDTest()
        {
            var timer = new Stopwatch();
            timer.Start();
            var objectGUIDMetaMapping = LdapConnection.GetAttributeMetaData("objectSid", LdapMetaMapFactory);
            Assert.IsTrue(objectGUIDMetaMapping.RawDotNetTypeEquivalent == typeof(byte[]));
            Assert.IsTrue(objectGUIDMetaMapping.SemanticDotNetTypeEquivalent == typeof(string));
            Assert.IsTrue(objectGUIDMetaMapping.SemanticValueConversionFunction == LdapValueDecoder.DecodeObjectSidValue);
            Assert.IsFalse(objectGUIDMetaMapping.IsMultiValued);
            Assert.IsFalse(objectGUIDMetaMapping.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("ObjectSid MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }

        [TestMethod]
        public void TestCaseSensativity()
        {
            var timer = new Stopwatch();
            timer.Start();
            var objectGUIDMetaMapping = LdapConnection.GetAttributeMetaData("ObJectGuID", LdapMetaMapFactory);
            Assert.IsTrue(objectGUIDMetaMapping.RawDotNetTypeEquivalent == typeof(byte[]));
            Assert.IsTrue(objectGUIDMetaMapping.SemanticDotNetTypeEquivalent == typeof(Guid));
            Assert.IsTrue(objectGUIDMetaMapping.SemanticValueConversionFunction == LdapValueDecoder.DecodeObjectGUIDValue);
            Assert.IsFalse(objectGUIDMetaMapping.IsMultiValued);
            Assert.IsFalse(objectGUIDMetaMapping.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("Test Case Sensativity took {0}", timer.ElapsedMilliseconds);
        }

        [TestMethod]
        public void TestNonExistantAttribute()
        {
            var timer = new Stopwatch();
            timer.Start();
            var nonExistingAttribute = LdapConnection.GetAttributeMetaData("IDoNotExist", LdapMetaMapFactory);
            Assert.IsNull(nonExistingAttribute);           
            timer.Stop();
            // Debug.WriteLine("Test Case NonExisting Attribute took {0}", timer.ElapsedMilliseconds);
        }

        // Testing vanila attribute
        [TestMethod]
        public void SamAccountName()
        {
            var timer = new Stopwatch();
            timer.Start();
            var samAccountNameAttribute = LdapConnection.GetAttributeMetaData("samaccountname", LdapMetaMapFactory);
            Assert.IsTrue(samAccountNameAttribute.RawDotNetTypeEquivalent == typeof(string));
            Assert.IsNull(samAccountNameAttribute.SemanticDotNetTypeEquivalent);
            Assert.IsNull(samAccountNameAttribute.SemanticValueConversionFunction);
            Assert.IsFalse(samAccountNameAttribute.IsMultiValued);
            Assert.IsFalse(samAccountNameAttribute.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("SamAccountName MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }

        [TestMethod]
        public void Member()
        {
            var timer = new Stopwatch();
            timer.Start();
            var memberAttribute = LdapConnection.GetAttributeMetaData("member", LdapMetaMapFactory);
            Assert.IsTrue(memberAttribute.RawDotNetTypeEquivalent == typeof(string));
            Assert.IsNull(memberAttribute.SemanticDotNetTypeEquivalent);
            Assert.IsNull(memberAttribute.SemanticValueConversionFunction);
            Assert.IsTrue(memberAttribute.IsMultiValued);
            Assert.IsTrue(memberAttribute.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("Member MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }


        // Int64 encoded time
        [TestMethod]
        public void LastLogonTimeStamp()
        {
            var timer = new Stopwatch();
            timer.Start();
            var lastLogonTimeStamp = LdapConnection.GetAttributeMetaData("lastlogontimestamp", LdapMetaMapFactory);
            // .NET sends int64encoded time values as strings
            Assert.IsTrue(lastLogonTimeStamp.RawDotNetTypeEquivalent == typeof(string));
            Assert.IsTrue(lastLogonTimeStamp.SemanticDotNetTypeEquivalent == typeof(DateTime));
            Assert.IsTrue(lastLogonTimeStamp.SemanticValueConversionFunction == LdapValueDecoder.DecodeInt64EncodedTimeValue);
            Assert.IsFalse(lastLogonTimeStamp.IsMultiValued);
            Assert.IsFalse(lastLogonTimeStamp.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("LastLogonTimeStamp metaMap creation took {0}", timer.ElapsedMilliseconds);
        }

        // GenerilizedTime
        [TestMethod]
        public void ModifyTimeStampTest()
        {
            var timer = new Stopwatch();
            timer.Start();
            var modifyTimeStamp = LdapConnection.GetAttributeMetaData("modifyTimeStamp", LdapMetaMapFactory);
            Assert.IsTrue(modifyTimeStamp.RawDotNetTypeEquivalent == typeof(string));
            Assert.IsTrue(modifyTimeStamp.SemanticDotNetTypeEquivalent == typeof(DateTime));
            Assert.IsTrue(modifyTimeStamp.SemanticValueConversionFunction == LdapValueDecoder.DecodeGeneralizedTime);
            Assert.IsFalse(modifyTimeStamp.IsMultiValued);
            Assert.IsFalse(modifyTimeStamp.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("ModifyTimeStamp MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }

        // GenerilizedTime
        [TestMethod]
        public void UserAccountControlTest()
        {
            var timer = new Stopwatch();
            timer.Start();
            var userAccountControl = LdapConnection.GetAttributeMetaData("userAccountControl", LdapMetaMapFactory);
            Assert.IsTrue(userAccountControl.RawDotNetTypeEquivalent == typeof(string));
            Assert.IsTrue(userAccountControl.SemanticDotNetTypeEquivalent == typeof(int));
            Assert.IsTrue(userAccountControl.SemanticValueConversionFunction == LdapValueDecoder.DecodeStringEncodedInt);
            Assert.IsFalse(userAccountControl.IsMultiValued);
            Assert.IsFalse(userAccountControl.ExpansionMayBeRequired);
            timer.Stop();
            // Debug.WriteLine("ModifyTimeStamp MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }

        [TestMethod]
        public void ThumbnailPhotoTest()
        {
            var timer = new Stopwatch();
            timer.Start();
            var thumbnailPhotoAttribute = LdapConnection.GetAttributeMetaData("thumbnailPhoto", LdapMetaMapFactory);
            Assert.IsTrue(thumbnailPhotoAttribute.RawDotNetTypeEquivalent == typeof(byte[]));
            Assert.IsNull(thumbnailPhotoAttribute.SemanticDotNetTypeEquivalent);
            Assert.IsNull(thumbnailPhotoAttribute.SemanticValueConversionFunction);
            Assert.IsFalse(thumbnailPhotoAttribute.IsMultiValued);
            Assert.IsFalse(thumbnailPhotoAttribute.ExpansionMayBeRequired);
            timer.Stop();
            Debug.WriteLine("ThumbnailPhotoTest MetaMap creation took {0}", timer.ElapsedMilliseconds);
        }


    }
}
